#pragma once

#include "giorgio.ugazio.h"
#include "math.h"
#include "../common/MathUtils.h"

bool GiorgioUgazio::Init(Register& o_register)
{
	m_name = "GIORGIO UGAZIO";

	REGISTER_FUNC5(GiorgioUgazio, 1, 2, 3, 15, 21);

	return true;
}

RetType GiorgioUgazio::Problem1()
{
	RetType sum = 0;
	for(UInt i=0; i<1000; ++i)
		if( (i%3 == 0) || (i%5 == 0))
			sum+=i;

	return sum;
}

RetType GiorgioUgazio::Problem2()
{
	RetType first = 1;
	RetType second = 2;
	RetType sum = 0;

	while(second < 4000000)
	{
		if(second%2 == 0)
			sum+= second;

		std::swap(first, second);
		second+=first;
	}

	return sum;
}

RetType GiorgioUgazio::Problem3()
{
	const UInt64 theNumber = 600851475143;
	UInt64 currentMax = 0;

	for(UInt64 i= 3; i*i<= theNumber; i+= 2)
	{
		if((theNumber % i) == 0)
			if(math::IsPrime(static_cast<UInt>(i)))
				currentMax = i;
	}

	return currentMax;
}

RetType Traversal(RetType vec[][21], const UInt a, const UInt b)
{
	if((a==0) || (b==0))
		return 1;
	if(vec[a][b] != 0)
		return vec[a][b];
	vec[a][b] = Traversal(vec,a-1,b) + Traversal(vec,a,b-1);
	return vec[a][b];
}

RetType GiorgioUgazio::Problem15()
{
	const UInt X = 20;
	const UInt Y = 20;
	RetType vec[X+1][Y+1];
	for(UInt i=0;i<=X;++i)
		for(UInt j=0;j<Y+1;++j)
			vec[i][j]=0;
	return Traversal(vec,X,Y);
}


UInt CalcSumDivisors(const UInt num)
{
	if((num==0) || (num==1))
		return 0;
	if(num==2)
		return 1;

	const UInt maxTest= static_cast<UInt>(sqrt(static_cast<Real32>(num))) + 1;

	UInt i = 2;
	UInt result = 1;

	while(i < maxTest)
	{
		if(num%i==0)
			result += i + num/i;
		++i;
	}
	return result;
}

RetType GiorgioUgazio::Problem21()
{
	std::vector<UInt> data(10000);
	for(UInt i=1; i<10000; ++i)
		data[i] = CalcSumDivisors(i);

	UInt count=0;
	for(UInt i=1; i<10000; ++i)
		if((data[i] < 10000) && data[data[i]] == i && data[i] != i)
			count += i;
	return static_cast<RetType>(count);
}
